package com.fivestar.pmanager.core.util;

import com.fivestar.pmanager.core.base.BaseBean;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.PropertyNamingStrategy.PropertyNamingStrategyBase;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.annotate.JsonView;
import org.codehaus.jackson.map.introspect.*;
import org.codehaus.jackson.map.ser.CustomSerializerFactory;
import org.codehaus.jackson.map.ser.FilterProvider;
import org.codehaus.jackson.map.ser.StdSerializerProvider;
import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;

import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * JSON数据工具类
 */
@SuppressWarnings("all")
public class JsonUtil
{
    private static ObjectMapper objectMapper = new ObjectMapper();

    

    /**
     * 
     * 转化实体为json字符串
     * 
     * @throws IOException
     */
    public static String writeEntity2Json(BaseBean entity) throws IOException
    {

        // writeValue具有和writeObject相同的功能
        StringWriter w = new StringWriter();
        objectMapper.writeValue(w, entity);

        return w.toString();
    }
    
    
    public static String writeObject2Json(Object o) throws JsonGenerationException, JsonMappingException, IOException
    {
        return objectMapper.writeValueAsString(o);
    }
    
    
    /**
     * 
     * 转化Map为json字符串
     * 
     * @throws JsonGenerationException
     * 
     * @throws JsonMappingException
     * 
     * @throws IOException
     */

    public static String writeMap2Json(Map<String, ?> map)
            throws JsonGenerationException, JsonMappingException, IOException
    {

        StringWriter w = new StringWriter();
        objectMapper.writeValue(w, map);

        return w.toString();
    }


    /**
     * 
     * 转化List为json字符串
     * 
     * @throws IOException
     * 
     * @throws JsonMappingException
     * 
     * @throws JsonGenerationException
     */

    public static String writeList2Json(List entityList)
            throws IOException
    {
        StringWriter w = new StringWriter();
        objectMapper.writeValue(w, entityList);

        return w.toString();
    }


    /**
     * 
     * 转化Json为对象 Json转换不能识别List中的对象类型，只能转成List<Map>类型 若要转成集合对象，请先转成对象数组
     * 再用Arrays.asList将其转换成List
     * 
     * @throws IOException
     * 
     * @throws JsonMappingException
     */

    public static Object readJson2Entity(String json, Class entityClass)
            throws IOException
    {
        Object o = objectMapper.readValue(json, entityClass);

        return o;
    }
    
    
    /**
     * 过滤属性
     *
     * @param clazz 元数据类
     * @param o 数据
     * @param properties 排除的属性
     * @return
     * @throws
     */
    public static String writeObject2Json(Class<?> clazz,Object o,String properties) throws JsonGenerationException, JsonMappingException, IOException
    {
        ObjectMapper mapper = new ObjectMapper(); 
        //添加自定义序列化
        addCustomSerializer(mapper);
        //添加过滤器
        FilterProvider filters = new SimpleFilterProvider().addFilter(clazz.getName(), SimpleBeanPropertyFilter.serializeAllExcept(properties.toLowerCase().split(","))); 
        mapper.setFilters(filters);
        //设置命名规则
        mapper.setPropertyNamingStrategy(new LowerPropertyNamingStrategy());
        return mapper.writeValueAsString(o);
    }
    
    
    /**
     * 将返回结果int、long、bigdecimal等等类型转换为String
     * @param Object 
     * @return
     * @throws
     */
    public static String writeObject2JsonValueString(Object o) throws JsonGenerationException, JsonMappingException, IOException
    {
        ObjectMapper mapper = new ObjectMapper(); 
        //属性名规则
        mapper.setPropertyNamingStrategy(new LowerPropertyNamingStrategy());
        //添加自定义序列化
        addCustomSerializer(mapper);
        return mapper.writeValueAsString(o);
    }
    
    
    /**
     * 添加自定义序列化
     *
     * @author fangsj
     * @param mapper 
     * @return
     * @throws
     */
    private static void addCustomSerializer(ObjectMapper mapper)
    {
        //声明自定义序列化工厂
        CustomSerializerFactory sf = new CustomSerializerFactory();  
        mapper.setSerializerFactory(sf);  
        //将基本类型转换字符串
        sf.addGenericMapping(Integer.class, new IntegerJsonSerializer()); 
        sf.addGenericMapping(Long.class, new LongJsonSerializer()); 
        sf.addGenericMapping(BigDecimal.class, new BigDecimalJsonSerializer()); 
        sf.addGenericMapping(Double.class, new DoubleJsonSerializer());
        sf.addGenericMapping(Float.class, new FloatJsonSerializer());
        sf.addGenericMapping(Short.class, new ShortJsonSerializer());
        sf.addGenericMapping(Date.class,new JsonDateSerializer());
        
        //统一处理null值
        StdSerializerProvider sp = new StdSerializerProvider();
        sp.setNullValueSerializer(new NullSerializer());
        mapper.setSerializerProvider(sp);
    }
    
    static class IntegerJsonSerializer extends JsonSerializer<Integer>
    {

        /* (non-Javadoc)
         * @author fangsj
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(Integer value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString(String.valueOf(value));
        }
        
    }

    static class JsonDateSerializer extends JsonSerializer<Date>
    {

        /**
         * Method that can be called to ask implementation to serialize
         * values of type this serializer handles.
         *
         * @param value    Value to serialize; can <b>not</b> be null.
         * @param jgen     Generator used to output resulting Json content
         * @param provider Provider that can be used to get serializers for
         */
        @Override
        public void serialize(Date value, JsonGenerator jgen,
                SerializerProvider provider)
                throws IOException, JsonProcessingException
        {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String formattedDate = formatter.format(value);
            jgen.writeString(formattedDate);
        }
    }

    static class LongJsonSerializer extends JsonSerializer<Long>
    {

        /* (non-Javadoc)
         * @author fangsj
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(Long value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString(String.valueOf(value));
        }
        
    }
    
    
    static class BigDecimalJsonSerializer extends JsonSerializer<BigDecimal>
    {

        /* (non-Javadoc)
         * @author fangsj
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(BigDecimal value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString(String.valueOf(value));
        }
        
    }
    
    
    static class FloatJsonSerializer extends JsonSerializer<Float>
    {

        /* (non-Javadoc)
         * @author fangsj
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(Float value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString(String.valueOf(value));
        }
        
    }
    
    static class DoubleJsonSerializer extends JsonSerializer<Double>
    {

        /* (non-Javadoc)
         * @author fangsj
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(Double value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString(String.valueOf(value));
        }
        
    }
    
    static class ShortJsonSerializer extends JsonSerializer<Short>
    {

        /* (non-Javadoc)
         * @author fangsj
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(Short value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString(String.valueOf(value));
        }
        
    }
    
    static class NullSerializer extends JsonSerializer<Object>
    {

        /* (non-Javadoc)
         * @author admin
         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
         */
        @Override
        public void serialize(Object value, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                JsonProcessingException
        {
            jgen.writeString("");
        }
        
    }
    
    static class LowerPropertyNamingStrategy extends PropertyNamingStrategyBase
    {

        /* (non-Javadoc)
         * @author admin
         * @see org.codehaus.jackson.map.PropertyNamingStrategy.PropertyNamingStrategyBase#translate(java.lang.String)
         */
        @Override
        public String translate(String propertyName)
        {
            return propertyName.toLowerCase();
        }
        
    }
    
    
    
}
